#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
数据结构定义模块，提供解析过程中使用的数据结构

开发者: 姜郑恒
职责: 实现数据结构定义，提供类信息、解析上下文等结构
"""
import copy
import time
from dataclasses import dataclass, field
from datetime import datetime
from typing import Dict, List, Optional, Set, Any, Tuple, Union
from enum import Enum


class ClassType(str, Enum):
    """类型枚举"""
    CLASS = "Class"
    INTERFACE = "Interface"
    ENUM = "Enum"
    ANNOTATION = "Annotation"
    UNKNOWN = "Unknown"


class Visibility(str, Enum):
    """可见性枚举"""
    PUBLIC = "public"
    PROTECTED = "protected"
    PRIVATE = "private"
    PACKAGE = "package"
    UNKNOWN = "unknown"


class DependencyType(str, Enum):
    """依赖类型枚举"""
    INHERITANCE = "inheritance"  # 继承关系
    IMPLEMENTATION = "implementation"  # 实现接口
    METHOD_CALL = "method_call"  # 方法调用
    FIELD_ACCESS = "field_access"  # 字段访问
    VARIABLE_TYPE = "variable_type"  # 变量类型
    PARAMETER_TYPE = "parameter_type"  # 参数类型
    RETURN_TYPE = "return_type"  # 返回值类型
    ANNOTATION = "annotation"  # 注解
    IMPORT = "import"  # 导入


@dataclass
class ClassInfo:
    """
    类信息数据类，存储类的基本信息
    
    属性:
        name: 类名
        full_name: 全限定类名(包含包路径)
        package: 包路径
        file_path: 文件路径
        imports: 导入语句列表
        is_parsed: 是否已解析
        metadata_extracted: 是否已提取元数据
        relationships_extracted: 是否已提取关系
    """
    name: str
    full_name: str
    package: str
    file_path: str
    imports: List[str] = field(default_factory=list)
    is_parsed: bool = False
    metadata_extracted: bool = False
    relationships_extracted: bool = False

    # 以下字段在详细解析阶段填充
    type: ClassType = ClassType.CLASS  # 类型(类/接口/枚举/注解)
    visibility: Visibility = Visibility.PUBLIC  # 可见性
    ast: Any = None               # 语法树缓存 (可选)
    is_abstract: bool = False     # 是否为抽象类
    is_static: bool = False       # 是否为静态类
    is_final: bool = False        # 是否为最终
    source_code: str = None       # 类源代码

    # 内部类
    is_inner_class: bool = False                # 是否为内部类
    outer_class_full_name: Optional[str] = None      # 外部类全限定名

    methods: List[str] = field(default_factory=list)  # 方法列表
    # fields: List[Dict] = field(default_factory=list)   # 字段列表
    super_classes: List[str] = field(default_factory=list)  # 父类列表
    implemented_interfaces: List[str] = field(default_factory=list)  # 实现的接口
    inner_classes: List[str] = field(default_factory=list)  # 内部类列表
    annotations: List[str] = field(default_factory=list)   # 注解列表

    def to_dict(self) -> Dict:
        """转换为字典表示"""
        return {
            "name": self.name,
            "full_name": self.full_name,
            "package": self.package,
            "file_path": self.file_path,
            "type": self.type,
            "visibility": self.visibility,
            "is_parsed": self.is_parsed,
            "is_abstract": self.is_abstract,
            "is_static": self.is_static,
            "is_final": self.is_final,
            "is_inner_class": self.is_inner_class,
            "outer_class_full_name": self.outer_class_full_name,
            "methods": self.methods.copy() if self.methods else [],
            "imports": self.imports.copy() if self.imports else [],
            "super_classes": self.super_classes.copy() if self.super_classes else [],
            "implemented_interfaces": self.implemented_interfaces.copy() if self.implemented_interfaces else [],
            "inner_classes": self.inner_classes.copy() if self.inner_classes else [],
            "annotations": self.annotations.copy() if self.annotations else []
        }


@dataclass
class ParserContext:
    """解析上下文，用于解析栈管理"""
    current_class: ClassInfo     # 当前解析的类
    current_position: int = 0    # 当前解析位置 (用于断点恢复)
    parsing_phase: str = "metadata"  # 当前解析阶段
    
    # 用于暂存部分解析结果
    temp_data: Dict = field(default_factory=dict)  
    
    def to_dict(self) -> Dict:
        """转换为字典表示"""
        return {
            "class_name": self.current_class.full_name,
            "position": self.current_position,
            "phase": self.parsing_phase
        }


@dataclass
class DependencyContext:
    """依赖解析上下文，用于处理类依赖关系"""
    source_class: str              # 源类全名
    dependent_class: str           # 依赖类全名
    file_path: str                 # 文件路径
    dependency_type: DependencyType  # 依赖类型

    # 上下文信息
    package: str = ""              # 当前包名
    imports: List[str] = field(default_factory=list)  # 导入列表
    
    def to_dict(self) -> Dict:
        """转换为字典表示"""
        return {
            "source_class": self.source_class,
            "dependent_class": self.dependent_class,
            "file_path": self.file_path,
            "dependency_type": self.dependency_type,
            "line_number": self.line_number,
            "package": self.package
        }


@dataclass
class RelationshipInfo:
    """关系信息，用于存储Java文件中提取的类、方法、字段之间的关系"""
    source_id: str                # 关系源实体ID
    target_id: str                # 关系目标实体ID
    relationship_type: str        # 关系类型 (继承、调用、引用等)
    properties: Dict[str, Any] = field(default_factory=dict)  # 关系属性

    def to_dict(self) -> Dict[str, Any]:
        """转换为字典表示"""
        return {
            "source_id": self.source_id,
            "target_id": self.target_id,
            "type": self.relationship_type,
            "properties": self.properties,
        }


@dataclass
class RelationshipCollection:
    """关系集合，用于存储从Java文件中提取的所有关系"""
    relationships: List[RelationshipInfo] = field(default_factory=list)  # 关系列表
    
    def add_relationship(self, relationship: RelationshipInfo) -> None:
        """添加一个关系到集合中"""
        self.relationships.append(relationship)
    
    def add_relationships(self, relationships: List[RelationshipInfo]) -> None:
        """添加多个关系到集合中"""
        self.relationships.extend(relationships)
    
    def to_dict(self) -> Dict[str, List[Dict[str, Any]]]:
        """转换为字典表示"""
        return {
            "relationships": [rel.to_dict() for rel in self.relationships]
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, List[Dict[str, Any]]]) -> 'RelationshipCollection':
        """从字典创建RelationshipCollection对象"""
        collection = cls()
        for rel_dict in data.get("relationships", []):
            relationship = RelationshipInfo(
                source_id=rel_dict.get("source_id", ""),
                target_id=rel_dict.get("target_id", ""),
                relationship_type=rel_dict.get("type", ""),
                properties=rel_dict.get("properties", {}),
            )
            collection.add_relationship(relationship)
        return collection


    

@dataclass
class GraphNodeInfo:
    """图数据库节点信息"""
    node_id: str           # 节点ID
    node_type: str         # 节点类型
    properties: Dict       # 节点属性
    
    
@dataclass
class GraphEdgeInfo:
    """图数据库边信息"""
    src_id: str           # 源节点ID 
    dst_id: str           # 目标节点ID
    edge_type: str        # 边类型
    properties: Dict      # 边属性


# 非实体信息, 仅用于函数参数列表
@dataclass
class ParameterInfo:
    """方法参数信息"""
    name: str          # 参数名
    type: str          # 参数类型

    def to_dict(self) -> Dict[str, str]:
        """转换为字典表示"""
        return {
            "name": self.name,
            "type": self.type
        }


@dataclass
class MethodInfo:
    """方法信息数据结构"""
    name: str                      # 方法名
    full_name: str                 # 方法全限定名
    # signature: str                 # 方法签名
    return_type: str = "void"      # 返回值类型
    visibility: Visibility = Visibility.PUBLIC  # 可见性
    is_static: bool = False        # 是否静态方法
    is_abstract: bool = False      # 是否抽象方法
    is_constructor: bool = False   # 是否构造方法
    parent_class: str = ""         # 所属类全名
    parameters: str = "()"             # 参数列表
    throws: List[str] = field(default_factory=list)  # 抛出异常列表
    annotations: List[str] = field(default_factory=list)  # 注解列表
    body: str = ""                 # 方法体

    def to_dict(self) -> Dict:
        """转换为字典表示"""

        return {
            "name": self.name,
            "full_name": self.full_name,
            "return_type": self.return_type,
            "visibility": self.visibility,
            "is_static": self.is_static,
            "is_abstract": self.is_abstract,
            "is_constructor": self.is_constructor,
            "parent_class": self.parent_class,
            "parameters": self.parameters,
            "throws": self.throws.copy() if self.throws else [],
            "annotations": self.annotations.copy() if self.annotations else [],
            "body": self.body
        }


@dataclass
class FieldInfo:
    """字段信息数据结构"""
    name: str                      # 字段名
    type: str                      # 字段类型
    visibility: Visibility = Visibility.PUBLIC  # 可见性
    is_static: bool = False        # 是否静态字段
    is_final: bool = False         # 是否常量
    parent_class: str = ""         # 所属类全名
    initialization: str = ""       # 初始化表达式
    annotations: List[Dict] = field(default_factory=list)  # 注解列表


@dataclass
class AnnotationInfo:
    """注解信息数据结构"""
    name: str                      # 注解名
    full_name: str                 # 全限定名
    target: List[str] = field(default_factory=list)  # 注解目标 (类/方法/字段)
    parameters: Dict[str, Any] = field(default_factory=dict)   # 注解参数

    def to_dict(self) -> Dict:
        """转换为字典表示"""
        return {
            "name": self.name,
            "full_name": self.full_name,
            "target": self.target.copy() if self.target else [],
            'parameters': self.parameters.copy() if self.parameters else {}
        }


@dataclass
class FileInfo:
    """文件信息结构"""
    # 基本信息
    file_path: str         # 文件的完整路径
    file_name: str         # 文件名
    package_name: str      # 包名
    extension: str         # 文件扩展名
    modification_time: str  # 最后修改时间
    size: int             # 文件大小（字节）

    def to_dict(self) -> Dict:
        """转换为字典表示"""
        return {
            "file_path": self.file_path,
            "file_name": self.file_name,
            "package_name": self.package_name,
            "extension": self.extension,
            "modification_time": self.modification_time,
            "size": self.size
        }

@dataclass
class CommentInfo:
    """注释信息数据结构"""
    target: str = ""        # 注解目标 (类/方法)的全限定名
    content: str = ""       # 注释内容

    def to_dict(self) -> Dict:
        """转换为字典表示"""
        return {
            "target": self.target,
            "content": self.content
        }

@dataclass
class PackageInfo:
    """包信息数据结构"""
    name: str  # 包名，例如 "com.example.mypackage"
    relative_path: str  # 包对应的目录的相对路径

    def to_dict(self) -> Dict:
        """转换为字典表示"""
        return {
            "name": self.name,
            "relative_path": self.relative_path
        }
    
@dataclass
class MetadataInfo:
    """元数据信息，用于存储Java文件解析后的元数据"""
    file_info: FileInfo = field(default_factory=lambda: FileInfo("", "", "", "", "", 0))  # 文件信息
    class_info: ClassInfo = field(default_factory=ClassInfo)  # 类信息列表
    methods: List[MethodInfo] = field(default_factory=list)  # 方法信息列表
    comments: List[CommentInfo] = field(default_factory=list)  # 注释信息列表
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典表示"""
        return {
            "file": self.file_info,
            "class_info": self.class_info,
            "methods": [method for method in self.methods],
            "comments": [comment for comment in self.comments]
        }

